home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / QuickDraw™ GX / Programming Stuff / Sample Code / Graphics Samples / QDGX Debugging (WWDC'94) ƒ / QDGX Debugging (WWDC'94).c < prev    next >
Encoding:
Text File  |  1995-04-10  |  24.0 KB  |  674 lines  |  [TEXT/KAHL]

  1. //
  2. //    These constants are used to turn on the good code (i.e. the non-buggy code)
  3. //
  4. #define kFixCallNewInkFirst                  //     fix the uninitialized gxInk problem
  5. #define kFixMoveScaleRotate                  //     fix the moving, scaling, and rotation into outer space problems
  6. #define kFixTextSize                      //     fix the text too small (i.e. using ints instead of fixed #'s) problem
  7. #define kFixOutliningOfText                  //     fix the outlining of the text to run along the character's geometry
  8. #define kAddPatternToRectangle            //    defining this flag calls the function which adds the pattern to the rectangle
  9. //#define kDrawBitmapPattern
  10. #define kFixPatternRotationFill             //     fix the funky bitmap rotation patterning problem...
  11. #define kDisposeTheCopyOfRectangleShape      //     dispose of the rectangle shape we copied into the picture
  12.   
  13. /**
  14.  --
  15.  --        App:            QDGX Debugging (WWDC'94) 
  16.  --
  17.  -- 
  18.  --        Version:        1.0     4/94:    added all of the calls required to support the "Using QuickDraw™ GX
  19.  --                                In QuickDraw Applications & Debugging Tips" session at the WWDC '94     
  20.  --
  21.  --
  22.  --        File:            QDGX Debugging (WWDC'94).c 
  23.  --
  24.  --
  25.  --        Comments:    This code creates a picture shape which contains the following shapes:
  26.  --
  27.  --                     - "G" and "X" as text shapes using the Skia font in 128 points, using a CMYK color,
  28.  --                     and an ADD transfer mode to allow color blending when shapes overlap.
  29.  --
  30.  --                    - two path shapes: one to outline the "G" and the other to outline the "X",
  31.  --                    which are draw as closed frame filled paths.
  32.  --
  33.  --                    - a rectangle shape in a light gray CMYK color
  34.  --
  35.  --                    As we create the shapes mentioned above, they are added to the picture
  36.  --                    shape - gThePage. We will then move this picture shape to the center of
  37.  --                    the window, scale it 3x, and rotate 15 degrees.
  38.  --
  39.  --                    Finally, we add a 15 degree rotated bitmap as a pattern to the rectangle.  This may
  40.  --                    seem straight forward, but the rotation of the bitmap shape causes some interesting
  41.  --                    problems and difficulties. See the comments with the "AddPatternedRectToPicture"
  42.  --                    function for complete details of these issues.
  43.  --
  44.  --                    This is the same code which was used during the"Using QuickDraw™ GX
  45.  --                    In QuickDraw Applications & Debugging Tips" session at the WWDC '94
  46.  --
  47.  --                    During our talk ay the WWDC '94, we demonstrated various bugs and debugging
  48.  --                    techniques. All of the "bugs" are controlled by the #defines below. If you want to see
  49.  --                    a particular bug, comment out the particular #define. There are comments regarding each
  50.  --                    #define below. 
  51.  --
  52.  --                    You can search on "BUG", to find all of the location we introduced a problem and a comment
  53.  --                    describing each fix...
  54.  --
  55.  --                    Also, you will need to install the "GXGraphics(debug)" extension to see and understand 
  56.  --                    all of the bugs. This extension also prevents a "bus error" from a bug within our code
  57.  --                    which GX validation will catch (if you are running the debugging extension).
  58.  --
  59.  --                    To receive the cool graphics effects, you need the following font installed into 
  60.  --                    your system: Skia (this font will be automatically installed, if you use the Installer Script)
  61.  --
  62.  --
  63.  --        Components:    QDGX Debugging (WWDC'94).c
  64.  --                    graphics shell.c
  65.  --                    graphics shell.h
  66.  --
  67.  --                    QDGX Debugging (WWDC'94).c contains all of the QuickDraw GX calls to draw and
  68.  --                    manipulate shapes. All of the interesting QuickDraw GX calls occur within this file.
  69.  --                    This file also contains the following function calls to make the graphics shell.c run
  70.  --                    correctly: DoInitialization, DoDraw, DoClick, DoDispose, DoIdle.
  71.  --
  72.  --                    graphics shell.c contains the event loop and all of the calls to initialize QuickDraw GX.
  73.  --
  74.  --
  75.  --        QuickDraw GX
  76.  --        Libraries
  77.  --        Used:        This application uses the following QuickDraw GX library code files:
  78.  --                    "color library.c", "font library.c", "graphics debug library.c", "qd library.c", 
  79.  --                    "transferMode library.c", and "transform library.c".
  80.  --                     
  81.  --        
  82.  --        Notes:            1) Print this file in landscape for the best results
  83.  --        
  84.  --                       2) If you are using THINK C v6.x, I have added THINK markers to navigate the code.
  85.  --        
  86.  --                    3) All of the functions are ordered in the order (top of this file to the bottom) they are called.
  87.  --
  88.  --
  89.  --        Authors:        Pete "Luke" Alexander          and      Herb Derby
  90.  --                    Developer Technical Support        QuickDraw GX Engineer
  91.  --                    AppleLink: DEVSUPPORT
  92.  --
  93.  --        
  94.  --        ©1992 - 1994  Apple Computer, Inc. 
  95.  --        All rights reserved.
  96.  --
  97. **/
  98.  
  99. #include <events.h>
  100. #include <windows.h>
  101.  
  102. #include "graphics libraries.h"
  103. #include "qd library.h"
  104. #include "font library.h"
  105. #include "graphics toolbox.h"
  106. #include "graphics debugging.h"
  107. #include "graphics shell.h"
  108.  
  109.  
  110. //
  111. //    Prototypes used _only_ within this file
  112. //
  113. void AddARectToPicture ( void  );
  114. void ColorTheRectInPicture ( void  );
  115. void ScaleAndRotateRectInPicture ( void  );
  116. void AddTextToPicture ( void  );
  117. void InitColorMatrix( Fixed xferModeMatrix[5][4] );
  118. void AddTransferModeToShape ( gxShape shapeWantingXferMode  );
  119. void AddPatternedRectToPicture ( void  );
  120.  
  121.  
  122. //
  123. //      Set up the title and size of the window 
  124. //
  125. Str255         gWindowTitle = "\p QuickDraw™ GX Debugging - WWDC '94 ";
  126. Rect             gWindowQDRect  = {50, 10, 475, 575};
  127.  
  128.  
  129. //
  130. //    gGraphicsHeapSize sets the size of the graphics heap created by calling the NewGraphicsClient routine
  131. //    in main () within graphics shell.c.  You can determine the amount of graphics heap required by using GraphicsBug.
  132. //    With  gGraphicsHeapSize set to 65k, I had 8 free blocks left in the QuickDraw GX heap. When I tried to 
  133. //    use a 65k, I received the disposed_dead_caches notice. This tells us the GX required additional memory to 
  134. //    complete an operation, therefore it needed to toss away outdated caches to complete the task. This is not necesarily
  135. //     bad, but an additional 8k solved this problem and prevented the disposing....
  136. //
  137. long            gGraphicsHeapSize = 72;
  138.  
  139. gxShape         gThePage;                    // the picture shape containing all of shapes created and drawn
  140.  
  141.  
  142.  
  143. /*------ DoInitialization ---------------------------------------------------------------------------------*/
  144. //
  145. //    This function creates the picture we want to add 5 shapes to and makes the appropriate function calls to 
  146. //    create them.
  147. //
  148. void DoInitialization(theWindow)
  149. WindowPtr theWindow;
  150. {
  151.     //
  152.     //    Create an empty picture shape to hold all of our shapes. After creating the picture shape, we can add
  153.     //    shapes at will....
  154.     //
  155.     gThePage = GXNewShape (gxPictureType); 
  156.     
  157.     AddTextToPicture ( );
  158.     AddARectToPicture ( );
  159.     ColorTheRectInPicture ( );
  160.     ScaleAndRotateRectInPicture ( );
  161.     
  162.     #ifdef kAddPatternToRectangle
  163.         AddPatternedRectToPicture ( );
  164.     #endif
  165. }
  166.  
  167.  
  168. /*------ InitColorMatrix --------------------------------------------------------------------------------*/
  169. //
  170. //    This function takes the matrix passed in and sets it to the identity. It was taken from the "transferMode libray.c".
  171. //
  172. void InitColorMatrix(Fixed xferModeMatrix[5][4])
  173. {
  174.     register Fixed         *x;
  175.     register int         loop;
  176.  
  177.     x = &xferModeMatrix[0][0];
  178.     
  179.     //
  180.     //    Initialize the matrix passed in to be filled full of 0's
  181.     //
  182.     for(loop = 19; loop >=0; loop--)
  183.         *x++ = 0;
  184.     
  185.     //
  186.     // Add the identity matrix, for cleanliness 
  187.     //    
  188.     xferModeMatrix[0][0] = xferModeMatrix[1][1] = xferModeMatrix[2][2] = xferModeMatrix[3][3] = fixed1;
  189. }
  190.  
  191.  
  192. /*------ AddTransferModeToShape -----------------------------------------------------------------------*/
  193. //
  194. //    This function creates an Add transfer mode.
  195. //
  196. void AddTransferModeToShape ( shapeWantingXferMode )
  197. gxShape shapeWantingXferMode;
  198. {
  199.     gxTransferMode    newAddTransferMode;
  200.     int                loop;
  201.  
  202.     newAddTransferMode.space             = gxCMYKSpace;
  203.     newAddTransferMode.flags             = 0;
  204.     newAddTransferMode.set                 = nil;
  205.     newAddTransferMode.profile             = nil;
  206.     
  207.     //
  208.     //    Set each component of the transfer mode..
  209.     //
  210.     for ( loop = 0; loop < 4; loop++ )
  211.     {
  212.         newAddTransferMode.component[ loop ].mode = gxAddMode;
  213.         newAddTransferMode.component[ loop ].flags = 0;
  214.  
  215.         newAddTransferMode.component[ loop ].operand = 0x8000;
  216.         
  217.         newAddTransferMode.component[ loop ].sourceMinimum = 0;
  218.         newAddTransferMode.component[ loop ].sourceMaximum = 65535;
  219.  
  220.         newAddTransferMode.component[ loop ].deviceMinimum = 0;
  221.         newAddTransferMode.component[ loop ].deviceMaximum = 65535;
  222.  
  223.         newAddTransferMode.component[ loop ].clampMinimum = 0;
  224.         newAddTransferMode.component[ loop ].clampMaximum = 65535;
  225.         
  226.     }
  227.  
  228.     //
  229.     //    Initialize each matrix used within the transfer mode to contain the identity matrix
  230.     //
  231.     InitColorMatrix( newAddTransferMode.sourceMatrix );
  232.     InitColorMatrix( newAddTransferMode.deviceMatrix );
  233.     InitColorMatrix( newAddTransferMode.resultMatrix );
  234.  
  235.     GXSetShapeTransfer( shapeWantingXferMode, &newAddTransferMode );
  236. }
  237.  
  238.  
  239. /*------ AddTextToPicture ------------------------------------------------------------------------------*/
  240. //
  241. //    This function creates the "G" and "X"  text shapes and the paths which outline each. The "G" and "X" text shapes
  242. //    are colored in a CMYK color using the Add transfer mode and the Skia Regular font (with it's bold axis set to it's 
  243. //    maximum). The Skia font is a new TrueType GX variation font. The outlines of the "G" and "X" text shapes are closed
  244. //    frame filled paths colored in back with the copy transfer mode. 
  245. //
  246. void AddTextToPicture ( )
  247. {
  248.     gxStyle             textStyle = GXNewStyle();
  249.     gxFont            theSkiaFont;
  250.     fixed                maxVariationValue;
  251.     gxFontVariation        fontVariation;
  252.     long                result;
  253.     gxColor            textColor, blackTextColor;
  254.     gxShape            textShape, tempTextShape;
  255.     gxPoint            textLocation = {  ff(0), ff(0) };
  256.     
  257.     //
  258.     //    Create a new style to contain: the font, font size, the 'wght' axis of the font set to the
  259.     //    maximum value allowed for this font, set the pen size, and the location of the pen when 
  260.     //    drawing.
  261.     //    
  262.     GXSetStylePen( textStyle, ff(2) );
  263.      
  264.          //
  265.          //    Here's a BUG, all numbers which are used as a parameter to a GX function must be in 
  266.          //    in fixed point. Otherwise, you will receive very, very, very, small numbers when ints are passed in.
  267.          //    The "ff" macro calls the IntToFixed (...) function.
  268.          //
  269.          #ifdef kFixTextSize
  270.         GXSetStyleTextSize( textStyle, ff(128) );
  271.     #else
  272.            GXSetStyleTextSize( textStyle, 128 );
  273.     #endif
  274.     
  275.     //
  276.     //    Create a GX font using the Skia regular font...
  277.     //
  278.     theSkiaFont = FindPNameFont ( gxFullFontName, "\pSkia Regular" );
  279.     GXSetStyleFont( textStyle, theSkiaFont );
  280.     
  281.     //
  282.     //     Here's a BUG (or unwanted behavior), since we are scaling and rotating our picture, we want to
  283.     //    turn "off" all of the metrics and hinting used by TrueType GX while it draws. If you do not turn them
  284.     //    off for the text, the outline for each character will not line up (i.e.  scale linearly) correctly.
  285.     //
  286.          #ifdef kFixOutliningOfText
  287.             GXSetStyleTextAttributes( textStyle, gxNoMetricsGridText | gxNoContourGridText );
  288.     #endif
  289.     
  290.     //
  291.     //    If the "result" is good, we proceed to set the "wght" axis to the maximum value. If the 
  292.     //    "result" is bad, this probably means that the "Skia" font has not been installed. In this
  293.     //    case we cannot set the "wght" axis, so we do not and we alert the user. We will be able 
  294.     //    to continue at this point, but we will not have the fat juicy letters.
  295.     //
  296.     result = GXFindFontVariation( theSkiaFont, 'wght', nil, nil, &maxVariationValue, nil );
  297.  
  298.     if (result) {
  299.         fontVariation.name     = 'wght';
  300.         fontVariation.value    = maxVariationValue;
  301.     
  302.          GXSetStyleFontVariations( textStyle, 1, &fontVariation );
  303.          
  304.     } else  DebugStr ("\p NO 'wght' axis....");
  305.  
  306.     //
  307.     //    Set up as CMYK color space which will used to color all of our text shapes. The "G" will
  308.     //    be colored in magenta. Each text shape will use a different CMYK color. We change the setting
  309.     //    for our "textColor" when we create each new shape.
  310.     //
  311.     textColor.space                 = gxCMYKSpace;
  312.     textColor.element.cmyk.cyan         = 0x0000;
  313.     textColor.element.cmyk.magenta     = 0xffff;
  314.     textColor.element.cmyk.yellow     = 0x0000;
  315.     textColor.element.cmyk.black         = 0x0000;
  316.     textColor.profile                 = nil;
  317.     
  318.     //
  319.     //    Create the "G", and set it's: style, transfer mode, color, and shape fill. Once created, add it to 
  320.     //    the end of our picture....
  321.     //
  322.     textShape = GXNewText (1, (unsigned char*) "G", &textLocation );
  323.      GXSetShapeStyle( textShape, textStyle );
  324.      GXSetShapeColor( textShape, &textColor );
  325.     AddTransferModeToShape ( textShape );        // This function is defined above to add the transfer mode to the "G"
  326.  
  327.      GXSetPictureParts( gThePage, 0, 0, 1, &textShape, nil, nil, nil );
  328.  
  329.     //
  330.     //    We create a unique copy of our "G" and convert it into a path shape to outline the "G". This outline will 
  331.     //    be in black using a copy transfer mode. We set the transfer mode to copy to prevent the printing system from
  332.     //    performing unneeded work...
  333.     //
  334.     tempTextShape = GXCopyToShape ( nil, textShape );
  335.     GXSetShapeType( tempTextShape, gxPathType ); 
  336.     GXSetShapeFill( tempTextShape,  gxClosedFrameFill );
  337.  
  338.     blackTextColor.space                 = gxCMYKSpace;
  339.     blackTextColor.element.cmyk.cyan         = 0x0000;
  340.     blackTextColor.element.cmyk.magenta     = 0x0000;
  341.     blackTextColor.element.cmyk.yellow     = 0x0000;
  342.     blackTextColor.element.cmyk.black         = 0xffff;
  343.     blackTextColor.profile                 = nil;
  344.     
  345.     SetShapeCommonTransfer (tempTextShape, gxCopyMode );
  346.     
  347.      GXSetShapeColor( tempTextShape, &blackTextColor );
  348.     GXSetPictureParts( gThePage, 0, 0, 1, &tempTextShape, nil, nil, nil  );
  349.  
  350.     GXDisposeShape( tempTextShape );  
  351.     GXDisposeShape( textShape );  
  352.     
  353.     //
  354.     //    Set the CYMK color to be cyan.
  355.     //
  356.     textColor.element.cmyk.magenta     = 0x0000;
  357.     textColor.element.cmyk.cyan         = 0xffff;
  358.     
  359.     //
  360.     //    Create the "X" text shape, set it's transfer mode to gxAddMode by calling our AddTransferModeToShape function, 
  361.     //    and set it's starting location, set the color, attach the style, and set the shape fill.
  362.     //
  363.     textLocation.x += ff( 60 );
  364.      textShape = GXNewText ( 1, (unsigned char*) "X", &textLocation );
  365.       GXSetShapeStyle( textShape, textStyle );
  366.     GXSetShapeColor( textShape, &textColor );
  367.     AddTransferModeToShape ( textShape );
  368.  
  369.     GXSetPictureParts( gThePage, 0, 0, 1, &textShape, nil, nil, nil );
  370.  
  371.     tempTextShape = GXCopyToShape ( nil, textShape );
  372.     
  373.     //
  374.     //    Create the outline of the "X". We convert our "X" text shape to a path, color it black, and set the fill to be 
  375.     //    closed frame.
  376.     //
  377.     GXSetShapeType( tempTextShape, gxPathType ); 
  378.     GXSetShapeFill( tempTextShape,  gxClosedFrameFill ) ;
  379.      GXSetShapeColor( tempTextShape, &blackTextColor );
  380.     SetShapeCommonTransfer (tempTextShape, gxCopyMode );
  381.  
  382.     GXSetPictureParts( gThePage, 0, 0, 1, &tempTextShape, nil, nil, nil );
  383.  
  384.     //
  385.     //    Dispose of the shapes and styles which are no longer needed. All of this information is now contained 
  386.     //    within our picture shape - gThePage.
  387.     //
  388.     GXDisposeShape( tempTextShape );  
  389.     GXDisposeShape( textShape );  
  390.     GXDisposeStyle( textStyle );  
  391. }
  392.  
  393.  
  394. /*------ AddARectToPicture -----------------------------------------------------------------------------*/
  395. //
  396. //    This function adds the background rectangle to our picture shape. We add this shape to the
  397. //    beginning of the picture.
  398. //
  399. void AddARectToPicture ( )
  400. {
  401.     gxShape            tempRectShape;
  402.     gxRectangle        pictureBounds;
  403.  
  404.     //
  405.     //    Get the bounds of the picture shape. At this point, it contains 4 shapes (2 text & 2 paths). The
  406.     //    bounding box will encompass the area required to draw all of the shapes created at this point. 
  407.     //    We will then inset the shape to provide better visual effects and color mixing.
  408.     //
  409.     GXGetShapeBounds( gThePage, 0, &pictureBounds );
  410.     
  411.     tempRectShape = GXNewRectangle( &pictureBounds );
  412.      GXInsetShape( tempRectShape, ff(10) );
  413.  
  414.      GXSetPictureParts( gThePage, 1, 0, 1, &tempRectShape, nil, nil, nil );
  415.  
  416.     GXDisposeShape( tempRectShape );  
  417. }
  418.  
  419.  
  420. /*------ ColorTheRectInPicture --------------------------------------------------------------------------*/
  421. //
  422. //    This function changes the color of your rectangle to be a light gray CMYK colored rectangle.
  423. //
  424. void ColorTheRectInPicture ( )
  425. {
  426.     gxColor        cmykColor;
  427.     //
  428.     //    Here's the BUG, you MUST call GXNew___ before using any GX object. If you have the "GXGraphics(debug)"
  429.     //    extension installed and validation turned on, you will receive a validation error, if you try to use an
  430.     //     uninitialized GX object. Otherwise, you will bus error...
  431.     //
  432.     #ifdef kFixCallNewInkFirst
  433.         gxInk         grayCMYKInk = GXNewInk ();
  434.     #else
  435.         gxInk         grayCMYKInk;
  436.     #endif
  437.     gxShape        rectShapeFromPicture;
  438.         
  439.     //
  440.     //    Create the light gray CMYK color 
  441.     //
  442.     cmykColor.space                 = gxCMYKSpace;
  443.     cmykColor.element.cmyk.cyan         = 0x0000;
  444.     cmykColor.element.cmyk.magenta     = 0x0000;
  445.     cmykColor.element.cmyk.yellow     = 0x0000;
  446.     cmykColor.element.cmyk.black         = 0x7000;
  447.     cmykColor.profile                 = nil;            // by passing nil, tells GX to not color match a shape
  448.                                                 // using this ink (color)...
  449.  
  450.     GXSetInkColor( grayCMYKInk, &cmykColor );
  451.  
  452.     GXGetPictureParts( gThePage, 1, 1, &rectShapeFromPicture, nil, nil, nil );
  453.     
  454.     GXSetShapeInk( rectShapeFromPicture, grayCMYKInk );
  455.  
  456.     GXDisposeInk ( grayCMYKInk );
  457. }
  458.  
  459.  
  460. /*------ ScaleAndRotateRectInPicture --------------------------------------------------------------------*/
  461. //
  462. //    This function moves our picture shape into the center of the window, scales it by 3, and rotates it (-15) degrees.
  463. //
  464. //    These macros are used within the function to determine the width and height of our picture and window.
  465. //
  466. #define width( r ) ((r).right - (r).left)
  467. #define height( r ) ((r).bottom - (r).top)
  468.  
  469. void ScaleAndRotateRectInPicture ( )
  470. {
  471.     gxRectangle     pictureBounds;
  472.     gxRectangle     windowBounds;
  473.     gxPoint         theCenter;
  474.     gxPoint         theTopLeft;
  475.     
  476.     GXGetShapeBounds( gWindowBoundsShape, 0, &windowBounds );
  477.     GXGetShapeBounds( gThePage, 0, &pictureBounds );
  478.     
  479.     //
  480.     //    Determine the center of the window
  481.     //
  482.     theCenter.x = width( windowBounds ) >> 1;
  483.     theCenter.y = height( windowBounds ) >> 1; 
  484.  
  485.     //
  486.     //    Determine the top left corner were we should place our picture shape to be in the center of the window
  487.     //
  488.     theTopLeft.x = theCenter.x - ( width( pictureBounds) >> 1 );
  489.     theTopLeft.y = theCenter.y + ( height( pictureBounds) >> 1 );
  490.     
  491.     //
  492.     //    Here's the BUG, you MUST move the shape before we scale and rotate it to prevent it from 
  493.     //    being transformed into outer space....
  494.     //
  495.     #ifdef kFixMoveScaleRotate
  496.         GXMoveShape( gThePage, theTopLeft.x, theTopLeft.y );
  497.         GXScaleShape( gThePage, ff(3), ff(3), theCenter.x, theCenter.y);
  498.         GXRotateShape( gThePage, -ff(15), theCenter.x, theCenter.y );
  499.     #else
  500.         GXScaleShape( gThePage, ff(3), ff(3), theCenter.x, theCenter.y);
  501.         GXRotateShape( gThePage, -ff(15), theCenter.x, theCenter.y );
  502.         GXMoveShape( gThePage, theTopLeft.x, theTopLeft.y );
  503.     #endif
  504. }
  505.  
  506.  
  507.  
  508. /*------ AddPatternedRectToPicture ---------------------------------------------------------------------*/
  509. //
  510. //    This function adds a bitmap shape as a pattern to our rectangle. The bitmap shape is rotated 45 degrees. This
  511. //    rotation causes an interesting problem which is described below.
  512. //
  513. void AddPatternedRectToPicture ( )
  514. {
  515.     gxShape            dogcowBitmapShape,
  516.                     tempRectShape , 
  517.                     rectShapeFromPicture,
  518.                     newBitmapClipShape;
  519.     gxRectangle         patternBounds;
  520.     gxPatternRecord    thePattern;
  521.     gxPolar            toRotate;
  522.     gxTransform        transformFromPicture, invertedTransform;
  523.     gxMapping            theMapping;
  524.     
  525.     //
  526.     //    Get the pixmap from the a resource file. If we fail in our attempt to create dogcowBitmapShape, 
  527.     //    GXValidateShape will let us know via the debugger. 
  528.     //
  529.     dogcowBitmapShape = GetPixMapShape( 128 );
  530.     GXValidateShape ( dogcowBitmapShape );
  531.  
  532.     GXGetShapeBounds( dogcowBitmapShape, 0L, &patternBounds);
  533.  
  534.     //
  535.     //    Turn off all attributes used by our bitmap shape. By default, the gxMapTransformShape shape
  536.     //    attribute is set for bitmap shapes. We turn this off because we want the rotation to occur on 
  537.     //    the geometry of our shape (i.e. the bits). This is required because the transform of the pattern's
  538.     //    shape is ignored once it has been added as a pattern shape. You can force the transform of the
  539.     //    pattern shape to be added to the shape by calling GXMapShape. This solves the previously described
  540.     //    problem, but the transform's clip is ignored when a shape is used as a pattern. We fix this problem below...
  541.     //
  542.     GXSetShapeAttributes( dogcowBitmapShape, gxNoAttributes );
  543.     
  544.     //
  545.     //    Here's part of the BUG,  we want to fill the rectangle with a bitmap shape rotated 45 degrees. So, we
  546.     //    rotate it. Ths kinda of works, but the clip shape is lost by the bitmap shape once it is added to the
  547.     //    pattern record. This is bad, because the bitmap shape is only partially drawn correctly. The bottom
  548.     //    half of the shape looks like corregated steel....
  549.     //
  550.     #if !defined(kFixPatternRotationFill) 
  551.          GXRotateShape( dogcowBitmapShape, ff(45), 0, 0 );
  552.     #endif
  553.  
  554.     #ifdef kDrawBitmapPattern
  555.          GXDrawShape ( dogcowBitmapShape );
  556.     #endif
  557.     
  558.     //
  559.     //    Set up the pattern record to allow our bitmap pattern shape be placed side by side.
  560.     //
  561.     thePattern.u.x             = 0;
  562.     thePattern.u.y             = (patternBounds.bottom - patternBounds.top) ;
  563.  
  564.     #ifdef kFixPatternRotationFill
  565.         thePattern.v.x             = (patternBounds.right - patternBounds.left) ;
  566.         thePattern.v.y             = 0;
  567.         thePattern.u.x             = 0;
  568.     #else
  569.         PointToPolar( &thePattern.u, &toRotate );
  570.         toRotate.angle += ff(45);
  571.         PolarToPoint( &toRotate, &thePattern.u );
  572.         
  573.         thePattern.v.x = (patternBounds.right - patternBounds.left);
  574.         thePattern.v.y = 0;
  575.     
  576.         PointToPolar( &thePattern.v, &toRotate );
  577.         toRotate.angle += ff(45);
  578.         PolarToPoint( &toRotate, &thePattern.v );
  579.     #endif
  580.  
  581.     thePattern.attributes = gxNoAttributes;
  582.     thePattern.pattern      = dogcowBitmapShape;
  583.  
  584.     GXGetPictureParts( gThePage, 1, 1, &rectShapeFromPicture, nil, nil, nil );
  585.     tempRectShape = GXCopyToShape ( nil, rectShapeFromPicture );
  586.  
  587.     GXSetShapePattern( tempRectShape, &thePattern );
  588.     
  589.     #ifdef kFixPatternRotationFill
  590.         transformFromPicture = GXGetShapeTransform ( gThePage );
  591.         invertedTransform = GXCopyToTransform( nil, transformFromPicture );
  592.         GXGetTransformMapping( invertedTransform, &theMapping );
  593.         
  594.         GXSetShapeAttributes( tempRectShape, gxNoAttributes );
  595.         GXSetShapeMapping( tempRectShape, &theMapping );
  596.         RotateMapping( &theMapping, -ff(45), 0, 0 );
  597.         GXMapShape( tempRectShape, &theMapping );
  598.  
  599.         InvertMapping( &theMapping, &theMapping );
  600.         GXSetTransformMapping( invertedTransform,  &theMapping );
  601.         
  602.         GXSetPictureParts( gThePage, 1, 1, 1, &tempRectShape, nil, nil, &invertedTransform );
  603.  
  604.         GXDisposeTransform( invertedTransform );  
  605.     #else
  606.         GXSetPictureParts( gThePage, 1, 1, 1, &tempRectShape, nil, nil, nil );
  607.     #endif
  608.  
  609.     #if !defined kDrawBitmapPattern
  610.         GXDisposeShape( dogcowBitmapShape );  
  611.     #endif
  612.  
  613.     #ifdef kDisposeTheCopyOfRectangleShape
  614.         GXDisposeShape( tempRectShape );  
  615.     #endif
  616. }
  617.  
  618.  
  619. /*------ DoDraw ---------------------------------------------------------------------------------------*/
  620. //
  621. //    This function performs all of the drawing by calling GXDrawShape on our picture - gThePage.
  622. //
  623. void DoDraw( theWindow )
  624. WindowPtr theWindow;
  625. {
  626.     GXDrawShape ( gThePage );
  627. }
  628.  
  629.  
  630. /*------ DoDispose -------------------------------------------------------------------------------------*/
  631. //
  632. //    This function tosses all of the shapes and the window we have created.
  633. //
  634. void DoDispose( theWindow )
  635. WindowPtr theWindow;
  636. {
  637.     //  
  638.     //    You should always dispose of your QuickDraw GX objects before tossing your window. Why? It's generally good 
  639.     //    form and this approach guarantees that everything is disposed. If you had not disposed of everything, the
  640.     //    call to DisposeWindow should dispose of the objects. If you are running the debugging version of the 
  641.     //    "GXGraphics(debug)" extension with warnings enabled, you will receive a warning that you had not disposed of
  642.     //    everything when you app quits. 
  643.     //
  644.     //    Notices are enabled within the "graphics shell.c" automatically, if you have installed the debug
  645.     //    extension. We determine if the debug extension is installed by making the appropriate Gestalt call while the
  646.     //    graphics shell is starting up; see the "graphics shell.c" file for details.
  647.     //
  648.     GXDisposeShape( gThePage );  
  649.      GXDisposeShape( gWindowBoundsShape );              // This shape is created within "graphics shell.c" at start up...
  650.         DisposeWindow( theWindow );
  651. }
  652.     
  653.  
  654.  
  655. /*------ DoClick ---------------------------------------------------------------------------------------*/
  656. //
  657. //    This function handles click by the user...
  658. //
  659. void DoClick( orgMouseLoc, theWindow )
  660. gxPoint        orgMouseLoc;
  661. WindowPtr     theWindow;
  662. {
  663. }
  664.  
  665.  
  666. /*------ DoIdle ----------------------------------------------------------------------------------------*/
  667. //
  668. //    This function is called within the event loop when the "graphics shell" receives a null event...
  669. //
  670. void DoIdle(theWindow)
  671. WindowPtr theWindow;
  672. {
  673. }
  674.